package top.kaoshanji.p2ch22b;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 代码清单-p2ch22b-575页b：具备单例作用域的DI容器类
 * author kaoshanji
 * ^_^
 * create time 2025/3/1 18:51
 */
public class SimpleContainer2 {

    // 这就是容器，用来持有 对象
    private static Map<Class<?>, Object> instanceMap = new ConcurrentHashMap<>();

    /**
     * 获取实例..那么就有点流程了
     * @param cls
     * @return
     * @param <T>
     */
    public <T> T getInstance(Class<T> cls) {
        try {

            // 1、如果是单例对象
            boolean singleton = cls.isAnnotationPresent(SimpleSingleton.class);
            if (!singleton) { // 不是单例对象就每次都创建
                return createInstance(cls);
            }

            // 2、看容器里面有没有...
            Object obj = instanceMap.get(cls);
            if (null != obj) {
                return (T) obj;
            }

            // 减少了锁同步的范围，提高了性能
            synchronized (cls) {
                obj = instanceMap.get(cls); // 再获取一次？？
                // 3、再才去创建
                if (null == obj) {
                    obj = createInstance(cls);
                    instanceMap.put(cls, obj);
                }
            }

            return (T) obj;

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    // 创建对象
    private <T> T createInstance(Class<T> cls) throws Exception {
        T obj = cls.newInstance();
        Field[] fields = cls.getDeclaredFields();
        for (Field field: fields) {
            // 需要注入的目标字段
            if (field.isAnnotationPresent(SimpleInject.class)) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }

                Class<?> fieldCls = field.getType();
                field.set(obj, getInstance(fieldCls));
            }

        }
        return obj;
    }

}
